package com.nextbus.main;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.google.android.maps.MapView;
import com.nextbus.database.DatabaseHelper;
import com.nextbus.model.RouteConfig;
import com.nextbus.model.Stop;
import com.nextbus.model.VehicleLocationsData;
import com.nextbus.parser.RouteConfigFeedParser;
import com.nextbus.parser.VehicleLocationsParser;
import com.nextbus.transit.TransitSystem;
import com.nextbus.ui.BusOverlay;
import com.nextbus.util.Constants;
import com.nextbus.util.HttpDownXMl;
import com.nextbus.util.ProgressMessage;
import com.nextbus.util.StreamCounter;

/**
 * 需要在后台完成的工作都交由该类完成， 该类与UpdateHandler类结合，Updater类 能够接收事件并且处理事情，也能够实现 定时更新
 * 
 * @author Administrator
 * 
 */
public class UpdateAsyncTask extends AsyncTask {
    private final static String TAG = "UpdateAsyncTask";

    // -------------------------------------全局变量 ---------------------------

    private Context context;

    private String routeToUpdate;

    private int viewMode;
    
    // -------------------------------------ProgressDialog------------------------
    private ProgressDialog pgsDialog;

    private String pgsTitle;

    private String pgsMessage;
    
   
    private int pgsProgress;

    private int pgsMax;

    private boolean pgsIsShowing;
     
    private ProgressBar pgsBar_updateStatus;
    
    private EditText editText_searchRoute;
    // -------------------------------------数据库相关的变量-------------------------

    private DatabaseHelper dbHelper;

    // -------------------------------------显示图层---------------------------------
    private MapView mapView;
    
  
    private BusOverlay busOverlay;
    private BusOverlay stopOverlay;
 
    // 暂时不实现
    // private RouteOverlay routeOverlay;

    public static final int EXE_TYPE = 1;

    // --------------------------------------暂时存储变量-------------------------------
    // 全部路线名
    ArrayList<String> routes;

    ArrayList<Stop> stops;

    ArrayList<VehicleLocationsData> buses;
    
    int operation_type;

    private String route;
    private String direction;
    //利用RouteConfig将站点的预测信息都保存起来
    private RouteConfig routeConfig;
    public UpdateAsyncTask() {

    }

    public UpdateAsyncTask(Context context, MapView mapView, ProgressDialog pgsDialog,BusOverlay busOverlay, 
    		BusOverlay stopOverlay,String route,String direction,ProgressBar pgsBar_updateStatus,
    		EditText editText_searchRoute) {
        this.context = context;
        this.pgsDialog = pgsDialog;
        this.busOverlay = busOverlay;
        this.stopOverlay = stopOverlay;
        this.mapView = mapView;
        this.route=route;
        this.direction=direction;
        this.dbHelper = new DatabaseHelper(context);
        this.pgsBar_updateStatus = pgsBar_updateStatus;
        this.editText_searchRoute=editText_searchRoute;
        
    }

    public UpdateAsyncTask(Context context, ProgressDialog pgsDialog) {
        this.context = context;
        this.pgsDialog = pgsDialog;
        this.dbHelper = new DatabaseHelper(context);
    }
   
 
    // -----------------------------------重载AsyncTask函数---------------------------------
    /**
     * 第一个被调用的函数
     */
    protected void onPreExecute() {
        super.onPreExecute();
    }

    /**
     * 第二个被调用的函数，doInBackground是另起线程进行的
     */
    protected Object doInBackground(Object... params) {
        operation_type = (Integer) params[0];
//        Log.d(TAG, "@doInBackground " + Thread.currentThread().getId());
        
        switch (operation_type) {
        case TransitSystem.OPERATION_TYPE_SEARCH_ROUTE:
        	return searchRoute();
        case TransitSystem.OPERATION_TYPE_CHANGE_VIEWMODE:
            return changeViewMode();
        case TransitSystem.OPERATION_TYPE_UPDATE_INSTANT:
            Log.d(TAG, "@doInBackground");
        	return updateInstant();    
        case TransitSystem.OPERATION_TYPE_PRESS_BUS:
        	return pressBusIcon();
        case TransitSystem.OPERATION_TYPE_PRESS_STOP:
        	 return pressStopIcon();
        case TransitSystem.OPERATION_TYPE_ADD_FAVORITE_STOP:
            break;
        case TransitSystem.OPERATION_TYPE_DELETE_FAVORITE_STOP:
            break;
        case TransitSystem.OPERATION_TYPE_GET_FAVORITE_STOPS:
            break;
        case TransitSystem.OPERATION_TYPE_INITDB:
            initSystemAtFirstInstallation();
            break;
        }
        return null;
    }
    
    public RouteConfig getRouteConfig(){
    	   this.routeConfig=dbHelper.getRouteConfig(route,direction,this);
           return routeConfig;
    }
    
    //  最后一个被调用的函数，doInBackground返回的Object是该函数的传入参数
    protected void onPostExecute(Object result) {
        super.onPostExecute(result);
        if (result == null) {
        	pgsBar_updateStatus.setVisibility(View.INVISIBLE);
            return;
        }
        
        switch (operation_type) {
        case TransitSystem.OPERATION_TYPE_SEARCH_ROUTE:
        case TransitSystem.OPERATION_TYPE_CHANGE_VIEWMODE://点击spinner的时候的更新操作
        case TransitSystem.OPERATION_TYPE_UPDATE_INSTANT://实时更新的操作
            Log.d(TAG, "@instant");
        	if (viewMode == Main.BUS_PREDICTIONS_ONE) {
                ArrayList<VehicleLocationsData> vehiclePredictions = (ArrayList<VehicleLocationsData>)result;
                busoverlayFresh(vehiclePredictions);
            } else if (viewMode == Main.STOP_PREDICTIONS_ONE) {
                Log.d(TAG, "@onPostExecute start");              
                stopoverlayFresh();
            }
            break;            
        case TransitSystem.OPERATION_TYPE_PRESS_BUS://选择了新路线以后的 	实时车辆的路线下载显示操作
        	ArrayList<VehicleLocationsData> vehiclePredictions = (ArrayList<VehicleLocationsData>)result;
        	busoverlayFresh(vehiclePredictions);
            break;            
        case TransitSystem.OPERATION_TYPE_PRESS_STOP: //选择了新路线以后的 	站点的信息下载，显示
        	stopoverlayFresh();      	 
            break;
        case TransitSystem.OPERATION_TYPE_ADD_FAVORITE_STOP:
            break;
        case TransitSystem.OPERATION_TYPE_DELETE_FAVORITE_STOP:
            break;
        case TransitSystem.OPERATION_TYPE_GET_FAVORITE_STOPS:
            break;
        case TransitSystem.OPERATION_TYPE_INITDB:
            break;
        }
        pgsBar_updateStatus.setVisibility(View.INVISIBLE);
    }
    
    
    //--------------------------------刷新overlay------------------------------------------
    private void  busoverlayFresh(ArrayList<VehicleLocationsData> vehiclePredictions) {
    	if (vehiclePredictions.size()!=0) {
			busOverlay.populateBusPrediction(vehiclePredictions);
			editText_searchRoute.setText(route+" "+direction);
            mapView.getOverlays().clear();	            
            mapView.getOverlays().add(busOverlay);
            mapView.invalidate();
		}else {
			Toast.makeText(context, "当前您选择的方向没有正在行驶的车辆，请稍后查看", Toast.LENGTH_LONG).show();
		}    	
        busOverlay.hide();
        stopOverlay.hide();
	}
    private void stopoverlayFresh() {
    	stopOverlay.populateStopList(routeConfig);
  	  	mapView.getOverlays().clear();
  	  	busOverlay.hide();
        stopOverlay.hide();
        mapView.getOverlays().add(stopOverlay);
  	  	mapView.invalidate();
	}

    
    
    // ----------------------------------------显示进度--------------------------
    public void publish(int i) {
        publishProgress(i);
    }

    public void publish(ProgressMessage message) {
        publishProgress(message);
    }

    // publishProgress之后，就会调用onPregressUpdate
    protected void onProgressUpdate(Object... values) {
        if (pgsDialog == null) {
            return;
        }
        Object obj = values[0];
        if (obj instanceof Integer) {
            int value = (Integer) obj;
            pgsDialog.setProgress(value);
            this.pgsProgress = value;
        }
        if (obj instanceof ProgressMessage) {
            ProgressMessage pm = (ProgressMessage) obj;
            switch (pm.type) {
            case ProgressMessage.PROGRESS_DIALOG_ON:
                if (pgsDialog != null) {
                    pgsDialog.setTitle(pm.title);
                    pgsDialog.show();
                }
                this.pgsTitle = pm.title;
                this.pgsMessage = pm.message;
                this.pgsIsShowing = true;
                break;
            case ProgressMessage.PROGRESS_OFF:
                break;
            case ProgressMessage.PROGRESS_SPINNER_ON:
                break;
            case ProgressMessage.SET_MAX:
                if (pgsDialog != null) {
                    pgsDialog.setMax(pm.max);
                }
                this.pgsMax = pm.max;
                break;
            case ProgressMessage.PROGRESS_DIALOG_OFF:
                if (pgsDialog != null) {
                    pgsDialog.hide();
                }
            case ProgressMessage.TOAST:
            	Toast.makeText(context, pm.message, Toast.LENGTH_LONG).show();
            	break;
            }
        }
    }

    // ------------------------------------用户操作具体对应的实现函数----------------
    public Object searchRoute() {
        return updateBusOrStopList();
    }
    
    public Object changeViewMode() {
        return updateBusOrStopList();
    }
    
    public Object updateInstant() {
        return updateBusOrStopList();
    }

    public Object pressBusIcon() {
        return getBusPredictionList();
    }

    public Object pressStopIcon() {
        return getRouteConfig();
    }

    public void addFavoriteStop() {

    }

    public void deleteFavoriteStop() {

    }

    public void getFavoriteStops() {

    }
    
    protected Object updateBusOrStopList() {
        if (viewMode == Main.BUS_PREDICTIONS_ONE) {
        	ArrayList<VehicleLocationsData> aData=getBusPredictionList();
            return aData;
        }
        else if (viewMode == Main.STOP_PREDICTIONS_ONE) {
            return getRouteConfig();
        }
        return null;
    }


    protected ArrayList<Stop> getStopList() {
        return dbHelper.getStopListByStopNameList(routeToUpdate);
    }

    protected ArrayList<VehicleLocationsData> getBusPredictionList()  {
        String url = TransitSystem.URL_BUS_PREDICTION + routeToUpdate+TransitSystem.URL_BUS_PREDICTION_TIME;
        String vehicleStr=null;  // 返回bus prediction xml的字符串        
		try {
			vehicleStr = HttpDownXMl.httpDownXml(url);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			publish(new ProgressMessage(ProgressMessage.TOAST,"1","请检查你的网络状态,目前下载不到信息"));
		}
		
        if (vehicleStr == null) {
            Log.d(TAG, "@getBusList 下载出错");
            return null;
        }
        
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            XMLReader reader = factory.newSAXParser().getXMLReader();
            VehicleLocationsParser parser = new VehicleLocationsParser();
            parser.setDirection(direction);
            // 为reader设置内容处理器
            reader.setContentHandler(parser);
            // 解析文件
            reader.parse(new InputSource(new StringReader(vehicleStr)));
            return parser.getVehicleLocationsDatas();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    

    public void initSystemAtFirstInstallation() {
        Log.d(TAG, "@initSystemAtFirstInstallation"
                + Thread.currentThread().getId());
        StreamCounter sc = new StreamCounter(context.getResources()
                .openRawResource(R.raw.routeconfig), this,
                Constants.ROUTE_CONFIG_BYTES);
        InputStream is = sc;
        try {
            publish(new ProgressMessage(ProgressMessage.PROGRESS_DIALOG_ON,
                    "Decompress the data", null));
            GZIPInputStream gin = new GZIPInputStream(is);
            RouteConfigFeedParser parser = new RouteConfigFeedParser(context);
            parser.runParse(gin);
            parser.writeInitDataToDB(this);
            Log.d(TAG, "size                 is    " + sc.getLength());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }
    }

    // -------------------------------------附加函数----------------------------------

    // 由于用户的操作而触发的操作
    public void triggerUpdate(int operation_type, String route, int viewMode) {
        Log.d(TAG, "@triggerUpdate");
        this.routeToUpdate = route;
        this.viewMode = viewMode;
        execute(operation_type);
    }

    
    public void runInstallDB() {
        execute(TransitSystem.OPERATION_TYPE_INITDB);
    }

    public void setProgress(ProgressDialog psgDialog) {
        this.pgsDialog = psgDialog;

        psgDialog.show();
    }


    public boolean isDBInstall() {
        // 首先判断空间够不够
        if (dbHelper.isRouteConfigDataInit()) {
            return true;
        }
        return false;
    }

    public boolean checkFreeSpace() {
        if (dbHelper.checkFreeSpace()) {
            return true;
        }
        return false;
    }

    // ----------------------------------getter and setter----------------------

    public DatabaseHelper getHelper() {
        return dbHelper;
    }

    public void setHelper(DatabaseHelper helper) {
        this.dbHelper = helper;
    }

}
